package kz.pdt12.hw.tests;

import com.thoughtworks.xstream.XStream;
import kz.pdt12.hw.data.ContactData;
import kz.pdt12.hw.data.GroupData;

import java.io.*;
import java.lang.reflect.Field;
import java.text.DateFormatSymbols;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Random;

/**
 * Created with IntelliJ IDEA.
 * User: raimbek
 * Date: 24.03.13
 * Time: 16:39
 */
public class DataGenerator {

    public static void main(String[] args) throws IOException, IllegalAccessException {
        if (args.length < 3) {
            System.out.println("Please specify parameters: <amount of test data> <object type> <format>");
            return;
        }

        int amount = Integer.parseInt(args[0]);
        String objectType = args[1];
        String format = args[2];

        List<?> objects = null;
        if (objectType.equals("groups")) {
            objects = generateRandomGroups(amount);
        } else if (objectType.equals("contacts")) {
            objects = generateRandomContacts(amount);
        }

        if (format.equals("csv")) {
            File file = new File(objectType + ".txt");
            saveObjectsToCsvFile(objects, file);
        } else if (format.equals("xml")) {
            File file = new File(objectType + ".xml");
            saveObjectsToXmlFile(objects, file);
        } else {
            System.out.println("Unknown format " + format);
            return;
        }
    }

    public static <E> void saveObjectsToXmlFile(List<E> objects, File file) throws IOException {
        XStream xstream = new XStream();
        String xml = xstream.toXML(objects);
        FileWriter writer = new FileWriter(file);
        writer.write(xml);
        writer.close();
    }

    public static <E> List<E> loadObjectsFromXmlFile(File file) {
        XStream xstream = new XStream();
        return (List<E>) xstream.fromXML(file);
    }

    private static <E> void saveObjectsToCsvFile(List<E> objects, File file) throws IOException, IllegalAccessException {
        FileWriter writer = new FileWriter(file);
        String line = "";
        for (E object : objects) {
            Class objectClass= object.getClass();
            Field[] fields = objectClass.getFields();
            String fieldText;
            for (Field field : fields) {
                Object o = field.get(object);
                if (o == null) {
                    fieldText = "null,";
                } else {
                    fieldText = o.toString() + ",";
                }
                line += fieldText;
            }
            line += "!\n";
        }
        writer.write(line);
        writer.close();
    }

    public static <E> List<E> loadObjectsFromCsvFile(File file, Class objectClass)
            throws IOException, IllegalAccessException, InstantiationException {
        List<E> list = new ArrayList<E>();
        BufferedReader reader = new BufferedReader(new FileReader(file));

        Field[] fields = objectClass.getFields();

        String line = reader.readLine();
        while (line != null) {
            String[] part = line.split(",");
            E object = (E) objectClass.newInstance();

            for (int i = 0; i < part.length - 1; i++) {
                if (part[i] == null) {
                    fields[i].set(object, null);
                } else {
                    fields[i].set(object, part[i]);
                }

            }
            list.add(object);

            line = reader.readLine();
        }
        reader.close();
        return list;
    }

    public static <E> List<Object[]> wrapObjectsForDataProvider(List<E> objects) {
        List<Object[]> list = new ArrayList<Object[]>();
        for (E object : objects) {
            list.add(new Object[] {object});
        }
        return list;
    }

    public static List<GroupData> generateRandomGroups(int amount) {
        List<GroupData> list = new ArrayList<GroupData>();

        for (int i = 0; i < amount; i++) {
            GroupData group = new GroupData()
                    .withName(generateRandomString())
                    .withFooter(generateRandomString())
                    .withHeader(generateRandomString());
            list.add(group);
        }
        return list;
    }

    public static List<ContactData> generateRandomContacts(int amount) {
        List<ContactData> list = new ArrayList<ContactData>();

        for (int i = 0; i < amount; i++) {
            Random random = new Random();

            String month = new DateFormatSymbols(Locale.US).getMonths()[random(0, 11)] + "";

            ContactData contact = new ContactData()
                    .withFirstName(generateRandomString())
                    .withLastName(generateRandomString())
                    .withAddress(generateRandomString())
                    .withTelephoneHome(random.nextInt() + "")
                    .withTelephoneWork(random.nextInt() + "")
                    .withTelephoneMobile(random.nextInt() + "")
                    .withEmail(generateRandomString())
                    .withEmail2(generateRandomString())
                    .withBirthdayDay(random(1, 28) + "")
                    .withBirthdayMonth(month)
                    .withBirthdayYear(random(1960, 2000) + "")
                    .withSecondaryAddress(generateRandomString())
                    .withSecondaryHomePhone(generateRandomString());

            list.add(contact);
        }
        return list;
    }

    public static String generateRandomString() {
        List<Integer> charCodes = new ArrayList<Integer>();
        for (int i = 0; i < 128; i++) {
            charCodes.add(i);
        }

        Random random = new Random();
        int rnd = random.nextInt(4);
        switch (rnd) {
            case 0 : return "";
            case 3 : return null;
            default: return generateRandomString(10, null) + random.nextInt();
        }
    }

    public static String generateRandomString(int maxLengthString, String additionSymbols) {
        String randomString = "";
        Random random = new Random();

        // коды основных символов
        List<Integer> charCodes = new ArrayList<Integer>();
        for (int i = 97; i < 128; i++) {
            charCodes.add(i);
        }

        //добавить дополниельные символы
        if (additionSymbols != null) {
            for (int b : additionSymbols.getBytes()) {
                charCodes.add(b);
            }
        }

        for (int i = 0; i < maxLengthString; i++) {
            int index = random.nextInt(charCodes.size() - 1);
            int code = charCodes.get(index);
            randomString += (char) code ;
        }

        return randomString;
    }

    public static int random(int min, int max) {
        int n = (max-min) + 1;
        return (int) (Math.random()*n + min );
    }
}
